#ifndef RSUCTRL1
#define RSUCTRL1
#include <QObject>
#include <QTimer>
#include "obuinfo.h"
#include <QAbstractState>
#include <QTcpSocket>
#include <QString>

//设备状态：正常
const int DEV_STATUS_OK      = 0;
//设备状态：错误
const int DEV_STATUS_ERR     = 1;
//设备状态：正在打开
const int DEV_STATUS_OPENING = 2;
const int DEV_STATUS_CLOSING = 3;
const int DEV_STATUS_CLOSED  = 4;
//设备状态：初始值，内部使用
const int DEV_STATUS_INIT=999;

//命令执行成功
const static int ERR_SUCCESS = 0;
//超时，RSU设备无响应
const static int ERR_RSU_OVERTIME = -100;
//传入参数错误
const static int ERR_RSU_API_INPUT_ERROR = -1000;
// 设备未打开
const static int ERR_RSU_NOT_OPENED = -1001;

//其他错误
const static int ERR_RSU_OTHER = -2000;

class RsuCtrl : public QObject
{
    Q_OBJECT
public:
    explicit RsuCtrl(int id, QObject *parent = 0)
    {
        new (this) RsuCtrl(parent);
        this->setId(id);
    }

    explicit RsuCtrl(QObject *parent = 0);
    ~RsuCtrl();

public:
    void setId(int nId);
    int  getId();
private:
    int m_nId;

public:
    void openRsu(const QString &host,quint16 port);
    void closeRsu();
    int initRsu(int nInterval, int nPower, int nChannel);
    // 获取RSU信息
    int getRsuInfo();
    // 发射bst帧
    int detectObu();
    void tryReconnect();
    // 检查天线状态
    void checkRsuStatus();
    // 设置心跳方式,及心跳间隔
    void setHeartBeat(int nStyle,int nInterval);
    void startDetectObu(int nInterval);
    void stopDetectObu();
    // 该函数不好使,具体原因崔总也不是很清楚
    int releaseObu();
    // 该值搭配 releaseobu 函数使用 也不好使
    void setBeaconChangeInterval(int nInterval);
protected:
    // 发送初始化信息
    int initRsuRq();
    int initPrimRq(char *BeaconID, char *Time, int Profile, int MandApplicationlist, char *MandApplication, int Profilelist);

protected:
    // 封装帧数据，进行转义并增加帧头、帧序号、校验码、帧尾。
    void wrapFrame(QByteArray &data);
    // 封装并发送帧数据
    int  wrapAndSendFrame(QByteArray &data);
    void setStatus(const int newStatus);
    void modifyBeaconId();

private:
    int getValueWithConfine(int n, int nMin, int nMax);
    void fillCurrentTime(quint8 *Time);
    //发射 bst命令时用到
    int getCmdGroupLen(int cmdCount, const char *cmdGroup);
    quint8 getRSCTL();
    quint8 getXOR(const QByteArray &data);
    void expectResult(int nFrameType);

protected slots: // socket 槽函数
    void socketReadyRead();
    void socketStateChanged(QAbstractSocket::SocketState socketState);
    void socketError(QAbstractSocket::SocketError socketError);

protected: // 处理数据
    bool processDataRead(const QByteArray &dataRead, QByteArray *pExpectedFrame, quint8 nExpectedFrameType);
    bool processRawFrame(QByteArray &frame, QByteArray *pExpectedFrame, quint8 nExpectedFrameType);
    void processRsuFrame(quint8 nFrameIndex, quint8 nFrameType, const QByteArray &frame);
    void processRsuInitFrame(const QByteArray &frame);
    void processRsuInfoFrame(const QByteArray &frame);
    void processObuInitFrame(const QByteArray &frame);
    void processObuInfo(int nProfile, int nAppList, const QByteArray &baApp, const QByteArray &baObuCfg);
protected slots: // 定时器槽函数
    void detectObuTimeout();
    void handleNoResponseError();

signals:
    // 新的数据到达
    void newFrameArrived(quint8 nFrameIndex, quint8 nFrameType, const QByteArray &frame);
    // RSU信息初始化
    void rsuInited(int nRsuStatus, const QByteArray &baRsuInfo);
    // 获取RSU信息
    void rsuInfoGot(const QByteArray &baRsuInfo);
    // 检测到OBU信息
    void obuDetected(ObuInfo newObu);
    // 天线状态改变
    void statusChanged(int status);

private:
    QTcpSocket m_tcpSocket;
    QString m_sHost;
    quint16 m_nPort;
    int m_bstInterval;
    int m_rsuPower;
    int m_rsuChannel;
    int m_nHeartBeatStyle;
    int m_nHeartBeatInterval; // 最低10s

    quint8 m_frameIndex; //信息帧序列号
    int m_nExpectedFrameType;
    QTimer *m_pNoResponseTimer;
    int m_nNoResponseErrorCount;

    // 车道端通知天线发bst帧
    QTimer m_timerDetectObu;
    int m_status;           /*!< 设备状态 */
    qint64 m_nDevOKTime;    /*!< 设备连接正常时间，主要用于心跳检测 */

    // 相同Obu时间段内不检测  功能为完善
    int m_nBeaconChangeInterval;
    quint8 m_BeaconId[8];

    QByteArray m_dataRead; // socket读到的原始数据

};


#endif // RSUCTRL1

